package com.ZeroCarbon.service.impl;

import com.ZeroCarbon.domain.po.BalanceIntegral;
import com.ZeroCarbon.domain.po.UserBaseInfo;
import com.ZeroCarbon.exception.BusinessLogicException;
import com.ZeroCarbon.mapper.BalanceIntegralMapper;
import com.ZeroCarbon.prefix.RedisKey;
import com.ZeroCarbon.service.IBalanceIntegralService;
import com.ZeroCarbon.utils.EmailService;
import com.ZeroCarbon.utils.UserHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;

import static com.ZeroCarbon.exception.BusinessLogicException.ERROR_EXCEPTION;

@Service
@RequiredArgsConstructor
public class BalanceIntegralServiceImpl extends ServiceImpl<BalanceIntegralMapper, BalanceIntegral> implements IBalanceIntegralService {
    /**
     * 邮箱信息类
     */
    private final EmailService emailService;

    private final StringRedisTemplate redis;

    /**
     * 获取余额和积分
     */
    @Override
    public BalanceIntegral getBalanceIntegral() throws BusinessLogicException {
        //获取用户id
        String userId = UserHolder.getUser();
        //获取用户余额和积分
        try {
            return getById(userId);
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }

    /**
     * 更改账户余额和积分
     */
    @Override
    public void updateBalanceIntegral(BalanceIntegral balanceIntegral) throws BusinessLogicException {
        //获取用户id
        String userId = UserHolder.getUser();
        //更新账户构造器
        LambdaQueryWrapper<BalanceIntegral> updateBalanceWrapper = new LambdaQueryWrapper<BalanceIntegral>()
                .eq(BalanceIntegral::getId, userId);
        //返回更新结果
        try {
            //获取更新账户结果
            boolean updateBalance = update(balanceIntegral, updateBalanceWrapper);
            //更新账户失败的情况
            if (!updateBalance) {
                throw new BusinessLogicException("更新账户失败，请稍后重试");
            }
        } catch (BusinessLogicException e) {
            throw new BusinessLogicException(e.getMessage());
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }

    /**
     * 增加余额和积分
     *
     * @param id 目标用户id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMoneyAndIntegral(String id, double money, int integral) throws BusinessLogicException {
        //如果没有传入id，则使用当前用户id
        if (id.isEmpty()) {
            id = UserHolder.getUser();
        }
        //获取账户构造器
        LambdaQueryWrapper<BalanceIntegral> updateBalanceWrapper = new LambdaQueryWrapper<BalanceIntegral>()
                .eq(BalanceIntegral::getId, id);
        //记录账户信息
        BalanceIntegral balanceIntegral;
        try {
            //获取账户余额
            balanceIntegral = getById(id);
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
        //账户余额和积分修改
        balanceIntegral
                .setBalance(balanceIntegral.getBalance() + money)
                .setIntegral(balanceIntegral.getIntegral() + integral);
        try {
            //更新账户余额
            boolean updateBalance = update(balanceIntegral, updateBalanceWrapper);
            //更新账户失败
            if (!updateBalance) {
                throw new BusinessLogicException("更新用户余额失败，请稍后重试");
            }
        } catch (BusinessLogicException e) {
            throw new BusinessLogicException(e.getMessage());
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }

    /**
     * 获取验证码
     */
    @Override
    public void getBalanceVerificationCode(double money) throws BusinessLogicException {
        //生成6位随机验证码
        int code = (int) (Math.random() * 900000) + 100000;
        // 获取用户id
        String userId = UserHolder.getUser();
        // 获取用户信息
        UserBaseInfo baseInfo = Db.lambdaQuery(UserBaseInfo.class).eq(UserBaseInfo::getId, userId).select(UserBaseInfo::getEmail).one();
        // 获取邮箱
        String email = null;
        // 判断对应用户是否存在
        if (baseInfo != null) {
            email = baseInfo.getEmail();
        } else {
            throw new BusinessLogicException();
        }
        try {
            // 发送邮箱
            emailService.sendSimpleEmail(email, "零碳易行充值验证码", "【零碳易行】尊敬的用户，" +
                    "你的账号" + userId + "即将充值" + money + "元，请在网站输入验证码" + code + "完成充值（3分钟内有效）。" +
                    "请勿泄露给他人，如非本人操作请忽略本短信。");
            //将验证码保存到redis，并设置15分钟后过期
            redis.opsForValue().set(RedisKey.BALANCE_VERIFICATION + userId, String.valueOf(code), 3, TimeUnit.MINUTES);
        } catch (Exception e) {
            throw new RuntimeException(ERROR_EXCEPTION);
        }
    }

    /**
     * 校验验证码
     *
     * @param code 输入验证码
     */
    @Override
    public void verifyBalanceVerificationCode(String code) throws BusinessLogicException {
        // 获取用户id
        String userId = UserHolder.getUser();
        // 获取相关键
        String key = RedisKey.BALANCE_VERIFICATION + userId;
        // 从redis获取相关的值
        String verificationCode = redis.opsForValue().get(key);
        // 判断输入验证码与生成验证码是否相同
        if (!code.equals(verificationCode)) {
            throw new BusinessLogicException("充值码错误");
        }
    }
}
